﻿using Exam.infranstuctrue.Dto.Request.Exam;
using Exam.infranstuctrue.Dto.Respones;
using Exam.infranstuctrue.Dto.Respones.Exam;
using Exam.infranstuctrue.EFCore;
using Exam.infranstuctrue.IOC;
using Exam.infranstuctrue.Tools;
using Exam.infranstuctrue.Tools.Attributes;
using Exam.Service.Interface;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Exam.Service.Instance
{
    [Iinjection]
    public class QuestionBankServer : BaseService, IQuestionBankServer
    {
        private readonly ExamIOC _examIOC;

        public QuestionBankServer(ExamIOC examIOC)
        {
            _examIOC = examIOC;
        }

        /// <summary>
        /// 获取题库列表
        /// </summary>
        /// <param name="limit"></param>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <param name="IsPublic"></param>
        /// <param name="IsBan"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetQuestionBank(int page = 1, int limit = 10, string key = "", int IsPublic = -1, int IsBan = -1)
        {
            var questionbanks = await _examIOC._examQuestionBankEFCore.QueryAll(out int total, page, limit, o => o.QbcreateTime, false, d => d.Qbname.Contains(key)
             && (IsPublic == -1 || d.QbisPublish == IsPublic)
             && (IsBan == -1 || d.QbisBan == IsBan)).ToListAsync();
            var qbids = questionbanks.Select(d => d.Qbid).ToList();
            var questionbankdetalis = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => qbids.Contains(d.Qbdqbid)).ToListAsync();
            var qids = questionbankdetalis.Select(d => d.Qbqid).ToList();
            var questions = await _examIOC._examQuestionEFCore.QueryAll(d => qids.Contains(d.Qid)).ToListAsync();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<QuestionBankRes> questionBankRes = new List<QuestionBankRes>();
            foreach (var item3 in questionbanks)
            {
                var questionbankdetali = questionbankdetalis.Where(d => d.Qbdqbid == item3.Qbid);
                var questionqids = questionbankdetali.Select(d => d.Qbqid).ToList();
                var question = questions.Where(d => questionqids.Contains(d.Qid)).ToList();
                List<QuestionRes> questionRes = new List<QuestionRes>();
                foreach (var item in question)
                {
                    List<OptionRes> optionRes = new List<OptionRes>();
                    var option = options.Where(d => d.Oqid == item.Qid).ToList();
                    foreach (var item2 in option)
                    {
                        optionRes.Add(new OptionRes
                        {
                            Oid = item2.Oid,
                            Ocontent = item2.Ocontent,
                            OisRight = item2.OisRight,
                            Ocreatetime = item2.Ocreatetime,
                        });
                    }
                    questionRes.Add(new QuestionRes
                    {
                        Qid = item.Qid,
                        Qcontent = item.Qcontent,
                        Qexplain = item.Qexplain,
                        Qanalysi = item.Qanalysi,
                        Qanswer = item.Qanswer,
                        Qauthor = item.Qauthor,
                        QcreateTime = item.QcreateTime,
                        QisBan = item.QisBan,
                        QisCheck = item.QisCheck,
                        QisPublish = item.QisPublish,
                        Qlable = item.Qlable,
                        Qlv = item.Qlv,
                        Qstate = item.Qstate,
                        Qtype = item.Qtype,
                        opiton = optionRes,
                    });
                }
                questionBankRes.Add(new QuestionBankRes
                {
                    qbid = item3.Qbid,
                    qbcount = item3.Qbcount,
                    qbexplain = item3.Qbexplain,
                    qblabel = item3.Qblable,
                    qblv = item3.Qblv,
                    qbname = item3.Qbname,
                    qbispublic = item3.QbisPublish,
                    qbisban = item3.QbisBan,
                    qbno = item3.Qbno,
                    question = questionRes,
                });
            }
            return GetResult(1, "题库列表", data: (new
            {
                total = total,
                data = questionBankRes,
            }));
        }
        /// <summary>
        /// 添加题库
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> AddQuestionBank(QuestionBankDto dto)
        {
            ExamQuestionBank examQuestionBank = new ExamQuestionBank()
            {
                Qbid = Config.GUID(),
                Qbcount = dto.qbcount,
                QbcreateTime = DateTime.Now,
                Qbdesc = "",
                Qbexplain = dto.qbexplain,
                QbisBan = 0,
                QbisPublish = 0,
                Qblable = dto.qblabel,
                Qblv = dto.qblv,
                Qbname = dto.qbname,
                Qbno = dto.qbno,
                Qbstate = 1,
            };
            _examIOC._examQuestionBankEFCore.Add(examQuestionBank);
            var result = await _examIOC._examQuestionBankEFCore.SaveChangesAsync();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "添加成功" : "添加失败");
        }
        /// <summary>
        /// 删除题库
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns 
        public async Task<ApiResult> DeleteQuestionBank(List<QuestionBankDto> dto)
        {
            var qbids = dto.Select(d => d.qbid).ToList();
            var questionbanks = await _examIOC._examQuestionBankEFCore.QueryAll(d => qbids.Contains(d.Qbid)).ToListAsync();
            foreach (var item in questionbanks)
            {
                if (item.QbisPublish == 1)
                {
                    return GetResult(0, "已经发布不可删除");
                }
            }
            _examIOC._examQuestionBankEFCore.DeleteRange(questionbanks);
            var result = _examIOC._examQuestionBankEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "删除成功" : "删除失败");
        }
        /// <summary>
        /// 获取单个题库
        /// </summary>
        /// <param name="qbid"></param>
        /// <returns></returns>
        public async Task<ApiResult> GetEchoQuestionBank(string qbid, int page = 1, int limit = 10, string key = "")
        {
            var questionbank = await _examIOC._examQuestionBankEFCore.QueryAll(d => d.Qbid == qbid).SingleAsync();//获取单个题库
            var questionbankdetali = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => d.Qbdqbid == qbid).ToListAsync();//通过题库ID获取题库详情
            var qids = questionbankdetali.Select(d => d.Qbqid).ToList();//在题库详情里面获取试题ID列表
            var questions = await _examIOC._examQuestionEFCore.QueryAll(out int total, page, limit, d => d.QcreateTime, false, d => qids.Contains(d.Qid) && d.Qcontent.Contains(key)).ToListAsync();//通过试题ID获取试题列表
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();//通过试题ID获取选项
            List<QuestionRes> questionRes = new List<QuestionRes>();
            foreach (var item in questions)
            {
                List<OptionRes> optionRes = new List<OptionRes>();
                var option = options.Where(d => d.Oqid == item.Qid).ToList();//通过试题ID获取对应选项
                foreach (var item2 in option)
                {
                    optionRes.Add(new OptionRes
                    {
                        Ocontent = item2.Ocontent,
                        Oid = item2.Oid,
                        OisRight = item2.OisRight,
                        Oqid = item2.Oqid,
                    });
                }
                questionRes.Add(new QuestionRes
                {
                    Qanalysi = item.Qanalysi,
                    Qanswer = item.Qanswer,
                    Qauthor = item.Qauthor,
                    Qcontent = item.Qcontent,
                    QcreateTime = item.QcreateTime,
                    Qexplain = item.Qexplain,
                    Qid = item.Qid,
                    QisBan = item.QisBan,
                    QisCheck = item.QisCheck,
                    QisPublish = item.QisPublish,
                    Qlable = item.Qlable,
                    Qlv = item.Qlv,
                    Qstate = item.Qstate,
                    Qtype = item.Qtype,
                    opiton = optionRes,
                });
            }
            QuestionBankRes questionBankRes = new QuestionBankRes()
            {
                qbid = questionbank.Qbid,
                qbcount = questionbank.Qbcount,
                qbexplain = questionbank.Qbexplain,
                qblabel = questionbank.Qblable,
                qblv = questionbank.Qblv,
                qbname = questionbank.Qbname,
                qbno = questionbank.Qbno,
                qbispublic = questionbank.QbisPublish,
                qbisban = questionbank.QbisBan,
                question = questionRes,
            };
            return GetResult(1, "题库详情", data: (new
            {
                total = total,
                data = questionBankRes
            }));
        }
        /// <summary>
        /// 是否禁用
        /// </summary>
        /// <param name="qbid"></param>
        /// <returns></returns>
        public async Task<ApiResult> IsBan(List<QuestionBankDto> dto)
        {
            var qbids = dto.Select(d => d.qbid).ToList();
            var questionbanks = await _examIOC._examQuestionBankEFCore.QueryAll(d => qbids.Contains(d.Qbid)).ToListAsync();
            foreach (var item in questionbanks)
            {
                if (item.QbisBan == 1)
                {
                    item.QbisBan = 0;
                }
                else
                {
                    item.QbisBan = 1;
                }
            }
            _examIOC._examQuestionBankEFCore.UpdateRange(questionbanks);
            var result = _examIOC._examQuestionBankEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "修改成功" : "修改失败");
        }
        /// <summary>
        /// 是否发布
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> IsPublish(List<QuestionBankDto> dto)
        {
            var qbids = dto.Select(d => d.qbid).ToList();
            var questionbanks = await _examIOC._examQuestionBankEFCore.QueryAll(d => qbids.Contains(d.Qbid)).ToListAsync();
            foreach (var item in questionbanks)
            {
                if (item.QbisPublish == 1)
                {
                    item.QbisPublish = 0;
                }
                else
                {
                    item.QbisPublish = 1;
                }
            }
            _examIOC._examQuestionBankEFCore.UpdateRange(questionbanks);
            var result = _examIOC._examQuestionBankEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "修改成功" : "修改失败");
        }
        /// <summary>
        /// 修改题库
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> UpdateQuestionBank(QuestionBankDto dto)
        {
            var questionbank = await _examIOC._examQuestionBankEFCore.QueryAll(d => d.Qbid == dto.qbid).SingleAsync();
            questionbank.Qblable = dto.qblabel;
            questionbank.Qbcount = dto.qbcount;
            questionbank.Qbexplain = dto.qbexplain;
            questionbank.Qbname = dto.qbname;
            questionbank.Qbno = dto.qbno;
            _examIOC._examQuestionBankEFCore.Update(questionbank);
            var result = _examIOC._examQuestionBankEFCore.SaveChanges();
            return GetResult(1, "修改成功");
        }
        /// <summary>
        /// 移入试题 --自动
        /// </summary>
        /// <param name="lable"></param>
        /// <param name="lv"></param>
        /// <returns></returns>
        public async Task<ApiResult> ConstituteJoinQuestion(QuestionBankDto dto)
        {
            if (dto.qbcount < 0)
            {
                return GetResult(0, "数量不可以少于1");
            }
            var questionbank = await _examIOC._examQuestionBankEFCore.QueryAll(d => d.Qbid == dto.qbid).FirstOrDefaultAsync();
            var questionbankdetalis = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => d.Qbdqbid == dto.qbid).ToListAsync();
            if (questionbank == null)
            {
                return GetResult(0, "没有改题库");
            }
            if (questionbank.Qbcount < questionbankdetalis.Count() + dto.qbcount)
            {
                return GetResult(0, "超出题库上线");
            }
            var questionbankdetali = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => d.Qbdqbid.Contains(dto.qbid)).ToListAsync();
            var questionbankqids = questionbankdetali.Select(d => d.Qbqid).ToList();
            var questions = await _examIOC._examQuestionEFCore.QueryAll(d => !questionbankqids.Contains(d.Qid)
            && d.Qlable == dto.qblabel
            && d.Qlv == dto.qblv
            && d.QisPublish == 1
            && d.QisBan == 0).ToListAsync();
            var qids = questions.Select(d => d.Qid).ToList();
            var question = questions.Skip(0).Take((int)dto.qbcount).ToList();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<ExamQuestionBankDetali> examQuestionBankDetali = new List<ExamQuestionBankDetali>();
            foreach (var item in question)
            {
                examQuestionBankDetali.Add(new ExamQuestionBankDetali
                {
                    Qbdid = Config.GUID(),
                    Qbdesc = "",
                    Qbdqbid = dto.qbid,
                    QbisState = 1,
                    Qbqid = item.Qid,
                });
            }
            _examIOC._examQuestionBankDetaliEFCore.AddRange(examQuestionBankDetali);
            var result = _examIOC._examQuestionBankDetaliEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "添加成功" : "添加失败");
        }
        /// <summary>
        /// 获取题库没有的试题
        /// </summary>
        /// <param name="limit"></param>
        /// <param name="page"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiResult> GetQuestion(string qbid, int limit = 1, int page = 10, string key = "")
        {
            var questionbankdetali = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => d.Qbdqbid.Contains(qbid)).ToListAsync();
            var questionbankqids = questionbankdetali.Select(d => d.Qbqid).ToList();
            var questions = await _examIOC._examQuestionEFCore.QueryAll(o => o.QcreateTime, false, d => !questionbankqids.Contains(d.Qid)
            && d.Qcontent.Contains(key)
            && d.QisPublish == 1
            && d.QisBan == 0).ToListAsync();
            var qids = questions.Select(d => d.Qid).ToList();
            var options = await _examIOC._examoptionEFCore.QueryAll(d => qids.Contains(d.Oqid)).ToListAsync();
            List<QuestionRes> questionRes = new List<QuestionRes>();
            foreach (var item in questions)
            {
                List<OptionRes> optionRes = new List<OptionRes>();
                var otpion = options.Where(d => d.Oqid == item.Qid).ToList();
                foreach (var item2 in otpion)
                {
                    optionRes.Add(new OptionRes
                    {
                        Oid = item2.Oid,
                        Oqid = item2.Oqid,
                        Ocontent = item2.Ocontent,
                        OisRight = item2.OisRight,
                    });
                }
                questionRes.Add(new QuestionRes
                {
                    Qid = item.Qid,
                    Qcontent = item.Qcontent,
                    Qanswer = item.Qanswer,
                    Qexplain = item.Qexplain,
                    Qlable = item.Qlable,
                    Qlv = item.Qlv,
                    Qanalysi = item.Qanalysi,
                    opiton = optionRes
                });
            }
            return GetResult(1, "获取成功", questionRes);
        }

        /// <summary>
        /// 移入试题 --手动
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> ArtificialJoinQuestion(QuestionBankDetaliDto dto)
        {
            var questionbank = await _examIOC._examQuestionBankEFCore.QueryAll(d => d.Qbid == dto.qbdid).FirstOrDefaultAsync();
            var qbdids = dto.questiondetali.Count();
            var questionbankdetali = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => d.Qbdqbid == dto.qbdid).ToListAsync();
            if (questionbank == null)
            {
                return GetResult(0, "没有改题库");
            }
            if (questionbank.Qbcount < questionbankdetali.Count() + qbdids)
            {
                return GetResult(0, "超出题库上线");
            }
            List<ExamQuestionBankDetali> questionBankDetali = new List<ExamQuestionBankDetali>();
            foreach (var item in dto.questiondetali)
            {
                questionBankDetali.Add(new ExamQuestionBankDetali
                {
                    Qbdid = Config.GUID(),
                    Qbdesc = "",
                    Qbdqbid = dto.qbdid,
                    QbisState = 1,
                    Qbqid = item.qid,
                });
            }
            _examIOC._examQuestionBankDetaliEFCore.AddRange(questionBankDetali);
            var result = await _examIOC._examQuestionBankDetaliEFCore.SaveChangesAsync();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "添加成功" : "添加失败");
        }
        /// <summary>
        /// 移除试题
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public async Task<ApiResult> RemoveQuestion(QuestionBankDetaliDto dto)
        {
            var qids = dto.questiondetali.Select(d => d.qid).ToList();
            var questionbankdetali = await _examIOC._examQuestionBankDetaliEFCore.QueryAll(d => qids.Contains(d.Qbqid) && d.Qbdqbid.Contains(dto.qbdid)).ToListAsync();
            _examIOC._examQuestionBankDetaliEFCore.DeleteRange(questionbankdetali);
            var result = _examIOC._examQuestionBankDetaliEFCore.SaveChanges();
            return GetResult(result > 0 ? 1 : 0, result > 0 ? "删除成功" : "删除失败");
        }


    }
}


